/*
 * Copyright (c) 2025 CAX Conversion Project
 */
package com.comac.ins.bomt.controller;

import com.comac.ins.bomt.common.enums.BomDetailTypeEnum;
import com.comac.ins.bomt.domain.TrackInfoVo;
import com.comac.ins.bomt.domain.request.BomGenerateRequest;
import com.comac.ins.bomt.domain.request.StandardBomDetailModifyRequest;
import com.comac.ins.bomt.domain.request.StrengthBomDetailModifyRequest;
import com.comac.ins.bomt.domain.response.OriginalBomUploadResponse;
import com.comac.ins.bomt.domain.vo.*;
import com.comac.ins.bomt.service.BomExportService;
import com.comac.ins.bomt.service.BomGenerateService;
import com.comac.ins.bomt.service.BomManageService;
import com.comac.ins.bomt.service.BomQueryService;
import com.comac.ins.common.core.domain.R;
import com.comac.ins.common.core.exception.BizException;
import com.comac.ins.common.core.utils.BizAssertUtil;
import com.comac.ins.common.log.annotation.Digest;
import com.comac.ins.common.mybatis.core.page.PageQuery;
import com.comac.ins.common.mybatis.core.page.TableDataInfo;
import com.comac.ins.common.satoken.utils.LoginHelper;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.springframework.http.MediaType;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.text.MessageFormat;
import java.util.List;


/**
 * BOM控制器
 *
 * @author zhanghongyi
 * @date 2024/8/1 14:33
 * @description BomController
 */
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/biz/bom")
public class BomController {

    private final BomManageService bomManageService;

    private final BomQueryService bomQueryService;

    private final BomExportService bomExportService;

    private final BomGenerateService bomGenerateService;

    /**
     * 原始装机清单上传
     *
     * @param aircraftModel 机型
     * @param desc          描述
     * @param file          文件
     * @return 上传结果
     */

    @PostMapping(value = "/upload-original/{aircraftModel}", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
    @Digest(bizType = "biz-bom-upload-original", logFields = {"aircraftModel", "file?.getOriginalFilename()"})
    public R<OriginalBomUploadResponse> uploadOriginal(
        @NotBlank(message = "机型不能为空") @PathVariable String aircraftModel,
        @RequestPart("desc") String desc,
        @NotNull(message = "上传文件不能为空") @RequestPart("file") MultipartFile file
    ) {
        BizAssertUtil.notNull(file.getOriginalFilename(), "file name empty");
        BizAssertUtil.isTrue(file.getOriginalFilename().endsWith(".xlsx"), "please use xlsx to init");
        OriginalBomUploadResponse response = bomManageService.uploadOrigin(LoginHelper.getLoginUser(), file, aircraftModel, desc);
        return R.ok(response);
    }

    /**
     * 初始化记录上传
     *
     * @param aircraftModel 机型
     * @param desc          描述
     * @param file          文件（包含初始化标准装机清单和强度数模清单的Zip文件）
     * @return 上传结果
     */
    @PostMapping(value = "/upload-init/{aircraftModel}", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
    @Digest(bizType = "biz-bom-upload-init", logFields = {"aircraftModel", "file?.getOriginalFilename()"})
    public R<Void> uploadInit(
        @NotBlank(message = "机型不能为空") @PathVariable String aircraftModel,
        @RequestPart("desc") String desc,
        @NotNull(message = "上传文件不能为空") @RequestPart("file") MultipartFile file
    ) {
        BizAssertUtil.notNull(file.getOriginalFilename(), "file name empty");
        BizAssertUtil.isTrue(file.getOriginalFilename().endsWith(".zip"), "please use zip package file like C919_S11_标准装机清单.xlsx and C919_S11_强度数模清单.xlsx to init");
        bomManageService.uploadInit(LoginHelper.getLoginUser(), file, aircraftModel, desc);
        return R.ok("success");
    }

    /**
     * 模型状态清单上传
     *
     * @param aircraftModel 机型
     * @param file          文件（包含模型状态清单Csv的zip包，zip包内文件名形如S11.csv）
     * @return 上传结果
     */
    @PostMapping(value = "/upload-model-status/{aircraftModel}", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
    @Digest(bizType = "biz-bom-upload-model-status", logFields = {"aircraftModel", "track", "file?.getOriginalFilename()"})
    public R<Void> uploadModelStatus(
        @NotBlank(message = "机型不能为空") @PathVariable String aircraftModel,
        @NotBlank(message = "跟踪Id不能为空") @RequestPart("track") String track,
        @NotNull(message = "上传文件不能为空") @RequestPart("file") MultipartFile file
    ) {
        BizAssertUtil.notNull(file.getOriginalFilename(), "file name empty");
        BizAssertUtil.isTrue(file.getOriginalFilename().endsWith(".zip"), "please use zip package file like S11.csv to init");
        bomManageService.uploadModelStatus(LoginHelper.getLoginUser(), file, aircraftModel, track);
        return R.ok("success");
    }


    /**
     * 分页查询原始装机清单文件列表
     *
     * @param aircraftModel 机型
     * @return 原始装机清单文件列表
     */
    @GetMapping("/list-original/{aircraftModel}")
    public TableDataInfo<BizFileVo> listOriginal(
        @NotBlank(message = "机型不能为空") @PathVariable String aircraftModel,
        PageQuery pageQuery
    ) {
        assignPageQueryDefaultOrderBy(pageQuery);
        return bomQueryService.listOriginalByPage(LoginHelper.getLoginUser(), aircraftModel, pageQuery);
    }

    /**
     * 分页查询批次号列表
     *
     * @param aircraftModel 机型
     * @param bomDetailType SBOM-标准装机清单,QBOM-强度数模清单,QBOM_SBOM_CHANGE-强度数模清单与标准装机清单对比,MSTS_QBOM_CHANGE-模型状态清单与强度数模清单对比
     * @return 批次号列表
     */
    @GetMapping("/list-track/{aircraftModel}")
    public TableDataInfo<String> listTrack(
        @NotBlank(message = "机型不能为空") @PathVariable String aircraftModel,
        @NotBlank(message = "bom明细类型不能为空") String bomDetailType,
        PageQuery pageQuery
    ) {
        BomDetailTypeEnum detailType = BomDetailTypeEnum.getByType(bomDetailType);
        BizAssertUtil.notNull(detailType, "detail type not recognized");
        return bomQueryService.listTrackByPage(LoginHelper.getLoginUser(), aircraftModel, detailType, pageQuery);
    }
    /**
     * 分页查询批次号信息列表
     *
     * @param aircraftModel 机型
     * @param bomDetailType SBOM-标准装机清单,QBOM-强度数模清单,QBOM_SBOM_CHANGE-强度数模清单与标准装机清单对比,MSTS_QBOM_CHANGE-模型状态清单与强度数模清单对比
     * @return 批次号信息列表
     */
    @GetMapping("/list-track-info/{aircraftModel}")
    public TableDataInfo<TrackInfoVo> listTrackInfo(
        @NotBlank(message = "机型不能为空") @PathVariable String aircraftModel,
        @NotBlank(message = "bom明细类型不能为空") String bomDetailType,
        PageQuery pageQuery
    ) {
        BomDetailTypeEnum detailType = BomDetailTypeEnum.getByType(bomDetailType);
        BizAssertUtil.notNull(detailType, "detail type not recognized");
        return bomQueryService.listTrackInfoByPage(LoginHelper.getLoginUser(), aircraftModel, detailType, pageQuery);
    }


    /**
     * 分页查询BOM列表
     *
     * @param aircraftModel 机型
     * @param track         跟踪Id
     * @param bomDetailType SBOM-标准装机清单,QBOM-强度数模清单,QBOM_SBOM_CHANGE-强度数模清单与标准装机清单对比,MSTS_QBOM_CHANGE-模型状态清单与强度数模清单对比
     * @return BOM列表
     */
    @GetMapping("/list-bom/{aircraftModel}")
    public TableDataInfo<BomInfoVo> listBom(
        @NotBlank(message = "机型不能为空") @PathVariable String aircraftModel,
        @NotBlank(message = "跟踪Id不能为空") String track,
        @NotBlank(message = "明细类型不能为空") String bomDetailType,
        PageQuery pageQuery
    ) {
        assignPageQueryDefaultOrderBy(pageQuery);
        BomDetailTypeEnum detailType = BomDetailTypeEnum.getByType(bomDetailType);
        BizAssertUtil.notNull(detailType, "detail type not recognized");
        return bomQueryService.listBomByPage(LoginHelper.getLoginUser(), aircraftModel, track, detailType, pageQuery);
    }

    /**
     * 分页查询标准装机清单明细
     *
     * @param aircraftModel 机型
     * @param track         跟踪Id
     * @param groupType     主分组类型
     * @param name          名称（可选）
     * @param level         层级（可选）
     * @param version       版次（可选）
     * @param code          编码（可选）
     * @param sectionName   部段名称（可选）
     * @return 明细信息
     */
    @GetMapping("/bom-detail/standard/{aircraftModel}")
    public TableDataInfo<DetailStandardBomVo> queryStandardBomDetail(
        @NotBlank(message = "机型不能为空") @PathVariable String aircraftModel,
        @NotBlank(message = "跟踪Id不能为空") String track,
        @NotBlank(message = "主分组类型不能为空") String groupType,
        @RequestParam(required = false) String name,
        @RequestParam(required = false) String level,
        @RequestParam(required = false) String version,
        @RequestParam(required = false) String code,
        @RequestParam(required = false) String sectionName,
        PageQuery pageQuery
    ) {
        DetailStandardBomVo query = new DetailStandardBomVo();
        query.setCode(code);
        query.setLevel(level);
        query.setName(name);
        query.setVersion(version);
        query.setSectionName(sectionName);
        return bomQueryService.listStandardBomDetailByPage(LoginHelper.getLoginUser(), aircraftModel, track, groupType, query, pageQuery);
    }


    /**
     * 分页查询查询强度数模清单明细
     *
     * @param aircraftModel 机型
     * @param track         跟踪Id
     * @param groupType     主分组类型
     * @param name          名称（可选）
     * @param level         层级（可选）
     * @param version       版次（可选）
     * @param code          编码（可选）
     * @return 明细信息
     */
    @GetMapping("/bom-detail/strength/{aircraftModel}")
    public TableDataInfo<DetailStrengthBomVo> queryStrengthBomDetail(
        @NotBlank(message = "机型不能为空") @PathVariable String aircraftModel,
        @NotBlank(message = "跟踪Id不能为空") String track,
        @NotBlank(message = "主分组类型不能为空") String groupType,
        @RequestParam(required = false) String name,
        @RequestParam(required = false) String level,
        @RequestParam(required = false) String version,
        @RequestParam(required = false) String code,
        PageQuery pageQuery
    ) {
        DetailStrengthBomVo query = new DetailStrengthBomVo();
        query.setCode(code);
        query.setLevel(level);
        query.setName(name);
        query.setVersion(version);
        return bomQueryService.listStrengthBomDetailByPage(LoginHelper.getLoginUser(), aircraftModel, track, groupType, query, pageQuery);
    }

    /**
     * 分页查询查询跨批次强度数模清单明细
     *
     * @param aircraftModel 机型
     * @param groupType     主分组类型（可选）
     * @param subGroupType  子分组类型（可选）
     * @param name          名称（可选）
     * @param code          编码（可选）
     * @return 明细信息
     */
    @GetMapping("/bom-detail/strength-cross-track/{aircraftModel}")
    public TableDataInfo<DetailStrengthBomVo> queryStrengthCrossTrackDetail(
        @NotBlank(message = "机型不能为空") @PathVariable String aircraftModel,
        @RequestParam(required = false) String groupType,
        @RequestParam(required = false) String subGroupType,
        @RequestParam(required = false) String name,
        @RequestParam(required = false) String code,
        PageQuery pageQuery
    ){
        DetailStrengthBomVo query = new DetailStrengthBomVo();
        query.setCode(code);
        query.setSubGroupType(subGroupType);
        query.setName(name);
        query.setGroupType(groupType);
        query.setAircraftModel(aircraftModel);
        return bomQueryService.listStrengthCrossTrackDetailByPage(LoginHelper.getLoginUser(),query, pageQuery);
    }


    /**
     * 修改强度数模清单明细
     *
     * @param aircraftModel 机型
     * @param id            Bom Id
     * @param request       修改后的明细列表（修改和删除）
     */
    @PutMapping("/bom-detail/strength/{aircraftModel}/{id}")
    @Digest(bizType = "biz-bom-detail-strength-modify", logFields = {"aircraftModel", "id", "T(org.apache.commons.lang3.StringUtils).join(request?.deleteIds,',')", "T(org.apache.commons.lang3.StringUtils).join(request?.modifyDetails.![id],',')"})
    public R<Void> modifyStrengthBomDetail(
        @NotBlank(message = "机型不能为空") @PathVariable String aircraftModel,
        @NotBlank(message = "Bom Id不能为空") @PathVariable String id,
        @NotNull(message = "强度数模清单修改请求") @RequestBody StrengthBomDetailModifyRequest request) {
        request.checkParam();
        bomManageService.modifyStrengthBomDetail(LoginHelper.getLoginUser(), request.getModifyDetails(), request.getDeleteIds());
        return R.ok("success");
    }

    /**
     * 修改标准装机清单明细
     *
     * @param aircraftModel 机型
     * @param id            Bom Id
     * @param request       修改后的明细列表（修改和删除）
     */
    @PutMapping("/bom-detail/standard/{aircraftModel}/{id}")
    @Digest(bizType = "biz-bom-detail-strength-modify", logFields = {"aircraftModel", "id", "T(org.apache.commons.lang3.StringUtils).join(request?.deleteIds,',')", "T(org.apache.commons.lang3.StringUtils).join(request?.modifyDetails.![id],',')"})
    public R<Void> modifyStandardBomDetail(
        @NotBlank(message = "机型不能为空") @PathVariable String aircraftModel,
        @NotBlank(message = "Bom Id不能为空") @PathVariable String id,
        @NotNull(message = "标准装机清单明细列表") @RequestBody StandardBomDetailModifyRequest request) {
        request.checkParam();
        bomManageService.modifyStandardBomDetail(LoginHelper.getLoginUser(), request.getModifyDetails(), request.getDeleteIds());
        return R.ok("success");
    }


    /**
     * 分页查询强度数模清单Vs标准装机清单变更明细
     *
     * @param aircraftModel 机型
     * @param track         跟踪Id
     * @param groupType     主分组类型
     * @param name          名称（可选）
     * @param level         层级（可选）
     * @param version       版次（可选）
     * @param code          编码（可选）
     * @param changeType    变更类型（可选） NUMBER("换号"),SAME("版本一致"),CHANGE("升版"),ADD("新增"),DELETE("删除")
     * @return 明细信息
     */
    @GetMapping("/bom-detail/strength-standard-change/{aircraftModel}")
    public TableDataInfo<DetailStrengthStandardChangeVo> queryStrengthStandardChangeDetail(
        @NotBlank(message = "机型不能为空") @PathVariable String aircraftModel,
        @NotBlank(message = "跟踪Id不能为空") String track,
        @NotBlank(message = "主分组类型不能为空") String groupType,
        @RequestParam(required = false) String name,
        @RequestParam(required = false) String level,
        @RequestParam(required = false) String version,
        @RequestParam(required = false) String code,
        @RequestParam(required = false) String changeType,
        PageQuery pageQuery
    ) {
        DetailStrengthStandardChangeVo query = new DetailStrengthStandardChangeVo();
        query.setCode(code);
        query.setLevel(level);
        query.setName(name);
        query.setVersion(version);
        query.setChangeType(changeType);
        return bomQueryService.listStrengthVsStandardChangeDetailByPage(LoginHelper.getLoginUser(), aircraftModel, track, groupType, query, pageQuery);
    }

    /**
     * 分页查询模型状态清单Vs强度数模清单变更明细
     *
     * @param aircraftModel 机型
     * @param track         跟踪Id
     * @param groupType     主分组类型
     * @param name          名称（可选）
     * @param level         层级（可选）
     * @param version       版次（可选）
     * @param code          编码（可选）
     * @param changeType    变更类型（可选） NUMBER("组件升号")，SAME("版本相同")，MODEL_UPGRADE("建模升版")，COPY_UPGRADE("复制升版"),ADD("新增")，DELETE("删除")
     * @return 明细信息
     */
    @GetMapping("/bom-detail/status-strength-change/{aircraftModel}")
    public TableDataInfo<DetailStatusStrengthChangeVo> queryStatusStrengthChangeDetail(
        @NotBlank(message = "机型不能为空") @PathVariable String aircraftModel,
        @NotBlank(message = "跟踪Id不能为空") String track,
        @NotBlank(message = "主分组类型不能为空") String groupType,
        @RequestParam(required = false) String name,
        @RequestParam(required = false) String level,
        @RequestParam(required = false) String version,
        @RequestParam(required = false) String code,
        @RequestParam(required = false) String changeType,
        PageQuery pageQuery
    ) {
        DetailStatusStrengthChangeVo query = new DetailStatusStrengthChangeVo();
        query.setCode(code);
        query.setLevel(level);
        query.setName(name);
        query.setVersion(version);
        query.setChangeType(changeType);
        return bomQueryService.listStatusVsStrengthChangeDetailByPage(LoginHelper.getLoginUser(), aircraftModel, track, groupType, query, pageQuery);
    }


    /**
     * 导出
     *
     * @param bomDetailType bom内容类型 SBOM-标准装机清单,QBOM-强度数模清单,QBOM_SBOM_CHANGE-强度数模清单与标准装机清单对比,MSTS_QBOM_CHANGE-模型状态清单与强度数模清单对比
     * @param aircraftModel 机型
     * @param ids           Bom id列表
     */
    @PostMapping("/bom-export/{bomDetailType}/{aircraftModel}")
    @Digest(bizType = "biz-bom-export", logFields = {"aircraftModel", "bomDetailType", "T(org.apache.commons.lang3.StringUtils).join(ids,',')"})
    public void export(
        @NotBlank(message = "bom类型不能为空") @PathVariable String bomDetailType,
        @NotBlank(message = "机型不能为空") @PathVariable String aircraftModel,
        @NotNull(message = "Bom Id列表不能为空") @RequestParam List<Long> ids,
        HttpServletResponse response
    ) {
        BomDetailTypeEnum detailType = BomDetailTypeEnum.getByType(bomDetailType);
        BizAssertUtil.notNull(detailType, "bom detail type not recognized");
        bomExportService.exportBomByTypeAndIds(LoginHelper.getLoginUser(), aircraftModel, ids, detailType, response);
    }

    /**
     * 生成
     *
     * @param aircraftModel 机型
     * @param request       请求
     * @return 导出的Zip压缩包
     */
    @PostMapping("/bom-generate/{aircraftModel}")
    @Digest(bizType = "biz-bom-generate", logFields = {"aircraftModel", "request?.bomDetailType", "request?.compareTrack", "T(org.apache.commons.lang3.StringUtils).join(request?.bomIds,',')"})
    public R<TableDataInfo<BomInfoVo>> generate(
        @NotBlank(message = "机型不能为空") @PathVariable String aircraftModel,
        @NotNull(message = "请求体不能为null") @RequestBody BomGenerateRequest request
    ) {
        String bomDetailType = request.getBomDetailType();
        BomDetailTypeEnum detailType = BomDetailTypeEnum.getByType(bomDetailType);
        BizAssertUtil.notNull(detailType, MessageFormat.format("bomDetailType {0} not support", bomDetailType));
        switch (detailType) {
            case QBOM:
                bomGenerateService.beginGenerateStrength(LoginHelper.getLoginUser(), aircraftModel, request.getBomIds());
                break;
            case QBOM_SBOM_CHANGE:
                BizAssertUtil.notBlank(request.getCompareTrack(), "对比对象的Track不能为空");
                bomGenerateService.beginGenerateStrengthVsStandard(LoginHelper.getLoginUser(), aircraftModel, request.getCompareTrack(), request.getBomIds());
                break;
            case MSTS_QBOM_CHANGE:
                bomGenerateService.beginGenerateStatusVsStrength(LoginHelper.getLoginUser(), aircraftModel, request.getBomIds());
                break;
            default:
                throw new BizException(MessageFormat.format("bomDetailType {0} not implement", bomDetailType));
        }
        return R.ok("success");
    }

    /**
     * 默认分页按更新时间倒序排序
     *
     * @param pageQuery 分页查询
     */
    private void assignPageQueryDefaultOrderBy(PageQuery pageQuery) {
        if (StringUtils.isBlank(pageQuery.getOrderByColumn())) {
            pageQuery.setOrderByColumn("update_time");
        }
        if (StringUtils.isBlank(pageQuery.getIsAsc())) {
            pageQuery.setIsAsc("desc");
        }
    }

}
